"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
var Person = /** @class */ (function () {
    function Person() {
        this.name = '123';
    }
    Person.prototype.getName = function () {
        console.log(this.name);
    };
    return Person;
}());
var p1 = new Person();
p1.name = 'smd';
p1.getName();
// 定义存取器
var User = /** @class */ (function () {
    // myName: string;
    // constructor(myName: string) {
    //   this.myName = myName
    // }
    // 简便写法
    function User(myName) {
        this.myName = myName;
    }
    Object.defineProperty(User.prototype, "name", {
        get: function () {
            return this.myName;
        },
        set: function (val) {
            this.myName = val;
        },
        enumerable: false,
        configurable: true
    });
    return User;
}());
var user = new User('smd');
user.name = '123';
console.log(user.name); // 123
// readonly 的用法
var Animal = /** @class */ (function () {
    function Animal(name) {
        this.name = name;
    }
    Animal.prototype.getName = function (name) {
        // 错误 this.name = name // 无法分配到 "name" ，因为它是只读属性。  
    };
    return Animal;
}());
// 继承  // 包括 public protected private
var Person1 = /** @class */ (function () {
    function Person1(name, age) {
        this.name = name;
        this.age = age;
    }
    Person1.toString = function () {
        console.log('person1');
    };
    Person1.prototype.getName = function () {
        return this.name;
    };
    Person1.prototype.setName = function (name) {
        this.name = name;
    };
    return Person1;
}());
var Student = /** @class */ (function (_super) {
    __extends(Student, _super);
    function Student(name, age, stuNo) {
        var _this = _super.call(this, name, age) || this;
        _this.stuNo = stuNo;
        return _this;
    }
    Student.toString = function () {
        console.log('Student');
    };
    Student.prototype.getStuNo = function () {
        return this.stuNo;
    };
    return Student;
}(Person1));
var s1 = new Student('smd', 18, 1);
console.log(s1.name);
// 错误 console.log(s1.age); // 属性“age”受保护，只能在类“Person1”及其子类中访问
// 装饰器
// 类装饰器
function addNameEat(constructor) {
    constructor.prototype.name = 'smd';
    constructor.prototype.eat = function () { };
}
var Person2 = /** @class */ (function () {
    function Person2() {
    }
    Person2 = __decorate([
        addNameEat
    ], Person2);
    return Person2;
}());
var p = new Person2();
console.log(p.name);
p.eat();
// 装饰器工厂
function addNameEatFactory(name) {
    return function addNameEat(constructor) {
        constructor.prototype.name = name;
        constructor.prototype.eat = function () { };
    };
}
var Person3 = /** @class */ (function () {
    function Person3() {
    }
    Person3 = __decorate([
        addNameEatFactory('shuaige')
    ], Person3);
    return Person3;
}());
var p3 = new Person3();
console.log(p3.name);
p3.eat();
var c;
(function (c) {
    // 装饰器函数中的属性  只能多  不能少
    function repalceClass(constructor) {
        return /** @class */ (function () {
            function class_1() {
            }
            return class_1;
        }());
    }
    var Preson = /** @class */ (function () {
        function Preson() {
            this.name = 'smd';
        }
        Preson = __decorate([
            repalceClass
        ], Preson);
        return Preson;
    }());
    var p1 = new Preson();
    console.log(p1.name);
})(c || (c = {}));
// 属性装饰器   1.装饰属性    2.装饰方法
var d;
(function (d) {
    /**
     *
     * @param target 如果装饰的是实例属性  则target表示实例的原形
     * @param propertyKey 属性名
     */
    function upperCase(target, propertyKey) {
        console.log(target, propertyKey); // { getName: [Function (anonymous)], sum: [Function (anonymous)] } name （是Proson的原形）
        var value = target[propertyKey];
        var getter = function () { return value; };
        var setter = function (newVal) {
            value = newVal.toLocaleUpperCase();
        };
        if (delete target[propertyKey]) {
            Object.defineProperty(target, propertyKey, {
                get: getter,
                set: setter,
                enumerable: true,
                configurable: true
            });
        }
    }
    /**
     *
     * @param target 如果装饰的是静态属性  则target表示的是构造函数本身
     * @param propertyKey 属性名
     */
    function staticPropertyDecorator(target, propertyKey) {
        console.log(target, propertyKey); // [Function: Person] { age: 18 } age （Person本身）
    }
    /**
     *
     * @param target 如果装饰的是实例方法  则target表示的是构造函数的原形
     * @param propertyKey 方法名
     */
    function noEnumerable(target, propertyKey, discriptor) {
        console.log('noEnumerable', target);
        console.log('noEnumerable', propertyKey);
        discriptor.enumerable = false;
    }
    /**
   *
   * @param target 如果装饰的是实例方法  则target表示的是构造函数的原形
   * @param propertyKey 方法名
   */
    function toNumber(target, propertyKey, discriptor) {
        console.log('toNumber', target);
        console.log('toNumber', propertyKey);
        var oldMethod = discriptor.value; // 拿到老的方法
        discriptor.value = function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            args = args.map(function (item) { return parseFloat(item); });
            return oldMethod.apply(this, args); // 用处理之后的入参  执行原来的方法
        };
    }
    var Person = /** @class */ (function () {
        function Person() {
            this.name = 'smd'; // 实例属性
        }
        Person.prototype.getName = function () {
            console.log(this.name);
        };
        Person.prototype.sum = function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            return args.reduce(function (accu, item) { return accu + item; }, 0);
        };
        Person.age = 18; // 静态属性
        __decorate([
            upperCase
        ], Person.prototype, "name", void 0);
        __decorate([
            noEnumerable
        ], Person.prototype, "getName", null);
        __decorate([
            toNumber
        ], Person.prototype, "sum", null);
        __decorate([
            staticPropertyDecorator
        ], Person, "age", void 0);
        return Person;
    }());
    var p = new Person();
    console.log(p.sum('1', '2'));
})(d || (d = {}));
// 参数装饰器
var e;
(function (e) {
    // 在IOC容器中大放异彩 nest.js中大量使用参数装饰器
    /**
     *
     * @param target 静态成员时表示构造函数   非静态成员表示构造函数原形
     * @param methodsName 参数名称 login
     * @param paramIndex 参数索引
     */
    function addAge(target, methodsName, paramIndex) {
        console.log(target, methodsName, paramIndex);
        target.age = 10;
    }
    var Person = /** @class */ (function () {
        function Person() {
        }
        Person.prototype.login = function (userName, password) {
            console.log(this.age, userName, password);
        };
        __decorate([
            __param(1, addAge)
        ], Person.prototype, "login", null);
        return Person;
    }());
    var p = new Person();
    p.login('smd', 'sss'); // 10 smd sss
})(e || (e = {}));
// 装饰器的执行顺序
var f;
(function (f) {
    function classDecorator1() {
        return function (target) {
            console.log('classDecorator1');
        };
    }
    function classDecorator2() {
        return function (target) {
            console.log('classDecorator2');
        };
    }
    function PropertyDecorator(name) {
        return function (target, propertyName) {
            console.log('PropertyDecorator', propertyName, name);
        };
    }
    function MeghodDecorator() {
        return function (target, propertyName) {
            console.log('MeghodDecorator', propertyName);
        };
    }
    function ParameterDecrator() {
        return function (target, methodName, paramIndex) {
            console.log('ParameterDecrator', methodName, paramIndex);
        };
    }
    var Person = /** @class */ (function () {
        function Person() {
            this.name = '';
            this.age = 10;
        }
        Person.prototype.hello = function (p1, p2) {
        };
        __decorate([
            PropertyDecorator('name')
        ], Person.prototype, "name", void 0);
        __decorate([
            PropertyDecorator('age')
        ], Person.prototype, "age", void 0);
        __decorate([
            MeghodDecorator(),
            __param(0, ParameterDecrator()),
            __param(1, ParameterDecrator())
        ], Person.prototype, "hello", null);
        Person = __decorate([
            classDecorator1(),
            classDecorator2()
        ], Person);
        return Person;
    }());
    /*
    执行顺序规律
    PropertyDecorator name name
    PropertyDecorator age age
    ParameterDecrator hello 1
    ParameterDecrator hello 0
    MeghodDecorator hello
    classDecorator2
    classDecorator1
  
    1.类装饰器最后执行  后写的先执行（挨着类越近  越先执行）
    2.方法装饰器和参数装饰器同时存在时   先执行参数装饰器
    3.方法装饰器和属性装饰器    从上到下执行
    */
})(f || (f = {}));
// 抽象类
var g;
(function (g) {
    var Animal = /** @class */ (function () {
        function Animal() {
        }
        return Animal;
    }());
    // 多态： 同一个方法 不同的子类有不同的实现
    var Cat = /** @class */ (function (_super) {
        __extends(Cat, _super);
        function Cat() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Cat.prototype.speak = function () {
            console.log('喵喵');
        };
        return Cat;
    }(Animal));
    var Dog = /** @class */ (function (_super) {
        __extends(Dog, _super);
        function Dog() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Dog.prototype.speak = function () {
            console.log('汪汪');
        };
        return Dog;
    }(Animal));
    function double(val) {
        if (typeof val === 'string') {
            return val + val;
        }
        else if (typeof val === 'number') {
            return val * 2;
        }
    }
    double('1');
    double(1);
    // 错误 double(true) // 在函数不重载之前  可以传入除string  number之外的类型  但是重载之后就不行了
})(g || (g = {}));
